home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 16 / AMIGAplus Sonderheft 16 (1998)(ICP)(DE)[!].iso / pd / anwendungen / ispell-3.1.18src / addons / xspell.shar / Xspell.c < prev   
C/C++ Source or Header  |  1995-01-23  |  34KB  |  1,406 lines

  1. static char *progid = "Xspell 1.0b, 1 May 92 philipp@res.enst.fr";
  2.  
  3. /*
  4.  * Xspell: Philippe-Andre Prindeville, Telecom Paris 1 May 1992
  5.  *
  6.  *    This program tries to follow the interface offered by
  7.  *    conventional ispell, but with a window interface (Motif
  8.  *    in this case).  The code is fairly simply and straight-
  9.  *    forward.  I'm interested in ports to other toolkits,
  10.  *    bug fixes, suggestions, etc.
  11.  *
  12.  *    The code for saving and backing up the files is perhaps
  13.  *    not entirely thought-out.  I don't like the way vi does
  14.  *    its backups, but perhaps I should have found another way.
  15.  *
  16.  *    Related to this is adding a mode to run as a filter.  If
  17.  *    you have my patches to xmeditor, then you know that you
  18.  *    can pipe the selection through a filter.  Thus, you could
  19.  *    use Xspell with xmeditor if Xspell had a stdin filter-mode.
  20.  *    Something to add on a rainy day.
  21.  *
  22.  *    I will probably be accused of being fascist for hard-wiring
  23.  *    the window layout.  Tant pis.
  24.  *
  25.  *    Note:  the MOTION code doesn't work.  I was too lazy to get
  26.  *    it running...
  27.  */
  28.  
  29. #include "config.h"
  30. #include "ispell.h"
  31.  
  32. #include <stdio.h>
  33. #include <sys/file.h>
  34. #include <sys/types.h>
  35. #include <sys/socket.h>
  36. #include <varargs.h>
  37.  
  38. #include <Xm/Xm.h>
  39. #include <Xm/DialogS.h>
  40. #include <Xm/MessageB.h>
  41. #include <Xm/Form.h>
  42. #include <Xm/Frame.h>
  43. #include <Xm/Label.h>
  44. #include <Xm/Separator.h>
  45. #include <Xm/ScrolledW.h>
  46. #include <Xm/Text.h>
  47. #include <Xm/RowColumn.h>
  48. #include <Xm/PushB.h>
  49. #include <Xm/TextF.h>
  50. #include <Xm/List.h>
  51. #include <Xm/MwmUtil.h>
  52.  
  53. #define    min(a,b)    (((a)<=(b))?(a):(b))
  54.  
  55. #define    MAXRESP        BUFSIZ*8
  56.  
  57. #define    NCOLS        5        /* max... */
  58. #define    NENTRIES    8
  59.  
  60. #undef    DOMOTION
  61.  
  62. #define    LINELEN        100
  63.  
  64. #ifndef    CUNCAP
  65. #define    CUNCAP        '&'
  66. #endif
  67.  
  68. #ifndef SELECT_BROKEN
  69. #define    HighlightText(text, from, to)    XmTextSetSelection(text, from, to, 0L)
  70. #define    UnhighlightText(text, from, to)    XmTextClearSelection(text)
  71. #else
  72. #define    HighlightText(text, from, to)    XmTextSetHighlight(text, from, to, XmHIGHLIGHT_SELECTED)
  73. #define    UnhighlightText(text, from, to)    XmTextSetHighlight(text, from, to, XmHIGHLIGHT_NORMAL)
  74. #endif
  75.  
  76. #include <sys/stat.h>
  77.  
  78. #include <assert.h>
  79.  
  80. extern XtAppContext app_context;
  81. extern Widget    toplevel;
  82. extern Widget    actions;
  83. extern Widget    fileName;
  84. extern Widget    lineNumber;
  85. extern Widget    offsetNumber;
  86. extern Widget    text;
  87. extern Widget    textedit;
  88. extern Widget    list[];
  89. extern Widget    noBackupDialog;
  90. extern Widget    isReadonlyDialog;
  91. extern Widget    couldntSaveDialog;
  92. extern Widget    tempIsDialog;
  93. extern Widget    isModifiedDialog;
  94.  
  95. typedef    struct {
  96.     int        columns;
  97.     String    dictionary;
  98.     String    type;
  99.     Boolean    backup;
  100.     Boolean    haveCompounds;
  101.     Boolean    sortPossibilities;
  102. } AppData;
  103.  
  104. static AppData app_data;
  105.  
  106. #ifdef    DEBUG
  107. #define    dprintf        printf
  108. #define    dputc        putchar
  109. #else
  110. #define    dprintf        _dprintf
  111. #define    dputc(x)
  112. #endif
  113.  
  114. #include "buffer.h"
  115.  
  116. static FILE    *srvout, *srvin = NULL;
  117. static char    possibilities[MAXPOSSIBLE][INPUTWORDLEN + MAXAFFIXLEN];
  118. static int    quit, nslots, pcount;
  119. static short    nlines;
  120. static buf_t    buf;
  121.  
  122. static char    **filePtr = NULL;
  123.  
  124. static int    inputPending = 0;
  125.  
  126. static int    isBlocked = 0;
  127. #define Block()    (isBlocked = 1)
  128. #define    UnBlock() { isBlocked = 0; Parse(); }
  129.  
  130. #ifdef    DOMOTION
  131. static int    ignoreMotion = 1;
  132. #endif
  133.  
  134. extern void    CheckLine();
  135. extern void    Correct();
  136. extern void    PostWarning();
  137.  
  138. static void
  139. getbuf(bp, offset)
  140. buf_t *    bp;
  141. long    offset;
  142. {
  143.     char *nl;
  144.     int ret;
  145.     long size;
  146.  
  147.     if (bp->base) {
  148.     XtFree(bp->base);
  149.     bp->base = NULL;
  150.     }
  151.  
  152.     if (offset >= bp->size) {
  153.     bp->ptr = bp->base = NULL;
  154.     return;
  155.     }
  156.  
  157.     size = min(bp->size - offset, BUFSIZ);
  158.  
  159.     bp->base = (char *) XtMalloc(size + 1);    /* count the \0 */
  160.  
  161.     ret = XmTextGetSubstring(text, offset, size, size + 1, bp->base);
  162.  
  163.     assert(ret != XmCOPY_FAILED);
  164.  
  165.     bp->ptr = bp->base;
  166.     bp->size += bp->delta;
  167.     bp->offset = offset;
  168.  
  169.     bp->cnt = size;
  170.     bp->delta = 0;
  171.     bp->lineno++;
  172.     bp->wordlen = -1;
  173.  
  174.     /*
  175.      * perhaps if we don't find a \n, we should look for a space...
  176.      */
  177.     nl = strchr(bp->base, '\n');
  178.     if (nl)
  179.     bp->cnt = (++nl - bp->base);
  180.     else
  181.     bp->base[size] = '\n';
  182. }
  183.  
  184. static void
  185. PipeInputCb(dummy, fd, xtid)
  186. int dummy;
  187. int *fd;
  188. XtInputId *xtid;
  189. {
  190.     inputPending = 1;
  191.  
  192.     while (! isBlocked)
  193.     CheckLine(&buf);
  194. }
  195.  
  196. static void
  197. Connect(w)
  198. Widget w;
  199. {
  200.     int        srv[2], clnt[2];
  201.     int        pid, argc;
  202.     char     buf[BUFSIZ];
  203.     char    *argv[10];
  204.     XtInputId    *xtid;
  205.  
  206.     pipe(srv);
  207.     pipe(clnt);
  208.  
  209.     switch (pid = fork()) {
  210.     case -1:
  211.     perror("fork");
  212.     exit(1);
  213.     case 0:
  214.     dup2(srv[0], 0);
  215.     close(srv[0]); close(srv[1]);
  216.     dup2(clnt[1], 1);
  217.     close(clnt[0]); close(clnt[1]);
  218.  
  219.     argc = 0;
  220.     argv[argc++] = "ispell";
  221.     argv[argc++] = "-d";
  222.     argv[argc++] = app_data.dictionary;
  223.     argv[argc++] = "-T";
  224.     argv[argc++] = app_data.type;
  225.     if (app_data.haveCompounds)
  226.         argv[argc++] = "-C";
  227.     if (app_data.sortPossibilities)
  228.         argv[argc++] = "-S";
  229.     argv[argc++] = "-a";
  230.     argv[argc++] = NULL;
  231.  
  232.     execvp("ispell", argv);
  233.     perror("execl: ispell");
  234.     exit(1);
  235.     default:
  236.     close(clnt[1]);
  237.     close(srv[0]);
  238.     if (! (srvout = fdopen(srv[1], "w"))) {
  239.         fprintf(stderr, "fdopen: cannot open stream\n");
  240.         exit(1);
  241.     }
  242.  
  243.     if (! (srvin = fdopen(clnt[0], "r"))) {
  244.         fprintf(stderr, "fdopen: cannot open stream\n");
  245.         exit(1);
  246.     }
  247.  
  248.     xtid = XtAppAddInput(XtWidgetToApplicationContext(w), clnt[0],
  249.            XtInputReadMask, (XtCallbackProc) PipeInputCb, NULL);
  250.  
  251.     break;
  252.     }
  253. }
  254.  
  255. static void
  256. SessionEnd()
  257. {
  258.     WriteCmd(srvout, "#\n");
  259.     fclose(srvout);
  260. #if 0
  261.     fclose(srvin);
  262. #endif
  263. }
  264.  
  265. static void
  266. ReadFile(path, bp)
  267. char    *path;
  268. buf_t    *bp;
  269. {
  270.     struct stat    st;
  271.     char    *str;
  272.     XmString    xstr;
  273.     long    size, n;
  274.     FILE    *infile;
  275.  
  276.     if (access(path, W_OK)) {
  277.     bp->readonly = 1;
  278.     PostWarning(&isReadonlyDialog, "isReadonlyDialog", NULL, False);
  279.     }
  280.  
  281.     if (! (infile = fopen(path, "r"))) {
  282.     perror(path);
  283.     exit(1);
  284.     }
  285.  
  286.     if (fstat(fileno(infile), &st)) {
  287.     perror(path);
  288.     exit(1);
  289.     }
  290.  
  291.     size = st.st_size;
  292.  
  293.     if ((str = XtMalloc(size + 1)) == NULL) {
  294.     fprintf(stderr, "%s: out of memory\n", path);
  295.     exit(1);
  296.     }
  297.  
  298.     if((n = fread(str, sizeof(char), size, infile)) != st.st_size) {
  299.     fprintf(stderr, "%s: read is short\n", path);
  300.     exit(1);
  301.     }
  302.  
  303.     fclose(infile);
  304.  
  305.     str[size] = '\0';
  306.     XmTextSetString(text, str);
  307.     XtFree(str);
  308.  
  309.     bp->base = bp->ptr = NULL;
  310.     bp->offset = bp->cnt = bp->delta = 0;
  311.     bp->lineno = -1;
  312.     bp->size = size;
  313.     bp->changed = 0;
  314.     bp->filename = strdup(path);
  315.  
  316.     xstr = XmStringCreateSimple(path);
  317.     XtVaSetValues(fileName, XmNlabelString, xstr, NULL);
  318. }
  319.  
  320. static
  321. WriteFile (path, bp)
  322. char    *path;
  323. buf_t    *bp;
  324. {
  325.     FILE    *outfile;
  326.     int        n, size, offset;
  327.     char    *str;
  328.  
  329.     if (! (outfile = fopen(path, "w"))) {
  330.     perror(path);
  331.     return 1;
  332.     }
  333.  
  334.     str = malloc(BUFSIZ + 1);
  335.  
  336.     for (offset = 0; offset < bp->size; offset += size) {
  337.     size = BUFSIZ;
  338.     if (offset + size > bp->size) size = bp->size - offset;
  339.  
  340.     XmTextGetSubstring(text, offset, size, size + 1, str);
  341.  
  342.     n = fwrite(str, sizeof(char), size, outfile);
  343.  
  344.     if(n != size) {
  345.         perror("write");
  346.         fclose(outfile);
  347.         free(str);
  348.         return 1;
  349.     }
  350.     }
  351.  
  352.     free(str);
  353.  
  354.     if (fclose(outfile)) {
  355.     perror("close");
  356.     return 1;
  357.     }
  358.  
  359.     return 0;
  360. }
  361.  
  362. Parse()
  363. {
  364.     while (! isBlocked)
  365.     CheckLine(&buf);
  366. }
  367.  
  368. Loop()
  369. {
  370.     for (; ; ) {
  371.     XtAppMainLoop(app_context);
  372.     dprintf("Exited from XtAppMainLoop!\n");
  373.     }
  374. }
  375.  
  376.  
  377. static void
  378. StartFile ()
  379. {
  380.     int        lineno;
  381.     char    *slash;
  382.     char    *path = *filePtr;
  383. #ifdef    DOMOTION
  384.     void    MotionCB();
  385. #endif
  386.  
  387.     dprintf("StartFile(%s)\n", path);
  388.  
  389.     ReadFile(path, &buf);
  390.  
  391.     buf.tempname = strdup("/tmp/XspellXXXXXX");
  392.     mktemp(buf.tempname);
  393.  
  394.     if (! buf.readonly && WriteFile(buf.tempname, &buf))
  395.     PostWarning(&noBackupDialog, "noBackupDialog", NULL, True);
  396.  
  397.     XtVaGetValues(text, XmNrows, &nlines, NULL);
  398.  
  399.     XtVaGetValues(list[0], XmNvisibleItemCount, &nslots, NULL);
  400.  
  401.     XmTextSetTopCharacter(text, 0);
  402.     buf.topline = 0;
  403.  
  404. #if 0
  405.     if (slash = strrchr(buf.filename, '/')) ++slash;
  406.     else slash = buf.filename;
  407.     WriteCmd(srvout, "~%s\n", slash);
  408. #endif
  409.  
  410.     /*
  411.      * To get us started, we prime the motor...
  412.      */
  413.     (void)WriteLine(&buf);
  414. }
  415.  
  416. static void
  417. EndFile()
  418. {
  419.     /*
  420.      *
  421.      * If the file was read-only, put the buffer into the tempfile.
  422.      *
  423.      * Otherwise, if there buffer wasn't modified, OR it was but we
  424.      * wrote it successfully, then we can remove the backup file.
  425.      * Otherwise, we bombed writing the file out...
  426.      */
  427.     if (buf.changed && buf.readonly) {
  428.     if (! WriteFile(buf.tempname, &buf))
  429.         PostWarning(&tempIsDialog, "tempIsDialog", buf.tempname, True);
  430.         else
  431.         PostWarning(&couldntSaveDialog, "couldntSaveDialog", NULL, True);
  432.     } else if (! buf.changed || ! WriteFile(buf.filename, &buf))
  433.     unlink(buf.tempname);
  434.     else
  435.     PostWarning(&tempIsDialog, "tempIsDialog", buf.tempname, True);
  436.  
  437.     free(buf.tempname);
  438. }
  439.  
  440. int
  441. WriteLine(bp)
  442. buf_t    *bp;
  443. {
  444.     getbuf(bp, bp->offset + (bp->cnt + bp->delta));
  445.  
  446.     if (! bp->base) return 0;
  447.  
  448.     WriteCmd(srvout, "^%.*s", bp->cnt, bp->base);
  449.  
  450.     return bp->cnt;
  451. }
  452.  
  453. static void
  454. CheckLine (bp)
  455. buf_t    *bp;
  456. {
  457.     int        c, t, n, reliable;
  458.     long    pos;
  459.     char    word[INPUTWORDLEN], *s;
  460.     char    buf[BUFSIZ];
  461.  
  462.     if (quit) {
  463.     EndFile();
  464.     SessionEnd();
  465.     exit(0);
  466.     }
  467.  
  468.     if (fgets(buf, sizeof(buf), srvin) == NULL)
  469.     c = EOF;
  470.     else
  471.     c = buf[0];
  472.  
  473.     dprintf("<<<%s", buf);
  474.  
  475.     switch (c) {
  476.     case EOF:        /* very unexpected */
  477.     fprintf(stderr, "End of file!\n");
  478.     exit(1);
  479.  
  480.     case '\n':            /* time to do the next line... */
  481.     if (WriteLine(bp))
  482.         break;
  483.  
  484.     EndFile();        /* no more text remained, so close the file. */
  485.  
  486.     ++filePtr;
  487.     if (*filePtr) {        /* if there is another file, start it... */
  488.         StartFile();
  489.         break;
  490.     }
  491.  
  492.     SessionEnd();
  493.     exit(0);
  494.  
  495.     case '@':            /* this is the version string... */
  496.     s = &buf[1];        /* banner... */
  497.     break;
  498.  
  499.     case '*':            /* word is OK */
  500.     break;
  501.  
  502.     case '+':            /* derivative */
  503.     s = &buf[2];
  504.     dprintf("deriv.:%s", s);
  505.     break;
  506.  
  507.     case '&':            /* word is dubious */
  508.     s = &buf[1];
  509.     n = sscanf(s, " %s %d %d", word, &reliable, &pos);
  510.     pos--;            /* correct for uparrow we added */
  511.     dprintf("\"%s\" at %d(@%d), %d choices:", word,
  512.         pos + bp->delta, bp->offset + pos + bp->delta, reliable);
  513.     s = index(s, ':');    /* find colon... */
  514.     assert(s);
  515.     for (n = 0; ; ++n) {
  516.         c = *s++;        /* skip comma or colon */
  517.             if (c == '\n') break;
  518.             sscanf(s, " %[^,\n]", possibilities[n]);
  519.         dprintf(" \"%s\"", possibilities[n]);
  520.         s += 1 + strlen(possibilities[n]);    /* count the space... */
  521.     }
  522.     /* newline already eaten */
  523.     dputc('\n');
  524.     pcount = n;
  525.     bp->wordlen = strlen(word);
  526.     bp->ptr = bp->base + pos;
  527.     Correct (bp);
  528.     Block();
  529.     break;
  530.  
  531.     case '?':
  532.     s = &buf[1];
  533.     n = sscanf(s, " %s %d %d", word, &reliable, &pos);
  534.     pos--;            /* correct for uparrow we added */
  535.     dprintf("\"%s\" at %d(@%d), %d choices:",
  536.         word, pos + bp->delta, bp->offset + pos + bp->delta, reliable);
  537.     s = index(s, ':');    /* find colon... */
  538.     assert(s);
  539.     for (n = 0; ; ++n) {
  540.         c = *s++;        /* slip colon or comma */
  541.         if (c == '\n') break;
  542.         sscanf(s, " %[^,\n]", possibilities[n]);
  543.         dprintf(" \"%s\"", possibilities[n]); fflush(stdout);
  544.         s += 1 + strlen(possibilities[n]);    /* count space... */
  545.     }
  546.     /* newline already eaten */
  547.     dputc('\n');
  548.     pcount = n;
  549.     bp->wordlen = strlen(word);
  550.     bp->ptr = bp->base + pos;
  551.     Correct (bp);
  552.     Block();
  553.     break;
  554.  
  555.     case '#':
  556.     s = &buf[1];
  557.     n = sscanf(s, " %s %d", word, &pos);
  558.     pos--;            /* correct for uparrow we added */
  559.     dprintf("\"%s\" at %d(@%d)\n", word, pos + bp->delta,
  560.         bp->offset + pos + bp->delta);
  561.     pcount = 0;
  562.     bp->wordlen = strlen(word);
  563.     bp->ptr = bp->base + pos;
  564.     Correct (bp);
  565.     Block();
  566.     break;
  567.  
  568.     case '-':        /* gak! */
  569.     default:
  570.     fprintf(stderr, "Error: read '%c' (\\%03o) on connection\n", c, c);
  571.     exit(1);
  572.     break;
  573.     }
  574.     inputPending = 0;
  575. }
  576.  
  577. static void
  578. ListPossibilities()
  579. {
  580.     int            col, start, limit, nelems, i, resized = 0;
  581.     int            ncols = app_data.columns;
  582.  
  583.     /*
  584.      * What to do?  Throw away the extras??
  585.      */
  586. #if 0
  587.     if (pcount > (ncols * nslots)) {
  588.     resized = 1;
  589.     nslots = (pcount + (ncols - 1)) / ncols;
  590.     dprintf("resizing to %d!\n", nslots);
  591.     }
  592. #endif
  593.     
  594.     for (col = 0; col < ncols; ++col) {
  595.     XtVaGetValues(list[col], XmNitemCount, &nelems, NULL);
  596.  
  597.     if (resized)
  598.         XtVaSetValues(list[col], XmNvisibleItemCount, nslots, NULL);
  599.  
  600.     start = col * nslots;
  601.     limit = MIN(pcount, (col + 1) * nslots);
  602.     for (i = start; i < limit; i++) {
  603.         XmString xstr = XmStringCreateSimple(possibilities[i]);
  604.  
  605.         XmListAddItemUnselected(list[col], xstr, 0);
  606.         XmStringFree(xstr);
  607.     }
  608.  
  609.     if (nelems)
  610.         XmListDeleteItemsPos(list[col], nelems, 1);
  611.  
  612. #if 1
  613.     if (start >= pcount)
  614.         XtUnmapWidget(list[col]);
  615.     else
  616. #endif
  617.         XtMapWidget(list[col]);
  618.     }
  619. }
  620.  
  621. /*
  622.  * Shared with callback functions... along with buf
  623.  */
  624.  
  625. static void
  626. Correct(bp)
  627. buf_t *        bp;
  628. {
  629.     long        pos;
  630.     char        tmp[INPUTWORDLEN];
  631.     static int        lastline = -1;
  632.     XmString        xstr;
  633.  
  634.     pos = bp->offset + (bp->ptr - bp->base) + bp->delta;
  635.  
  636.     if (lastline != bp->lineno) {
  637.     int        nscroll;
  638.  
  639.     lastline = bp->lineno;
  640.     sprintf(tmp, "%u", bp->lineno + 1);
  641.     xstr = XmStringCreateSimple(tmp);
  642.     XtVaSetValues(lineNumber, XmNlabelString, xstr, NULL);
  643.  
  644.     nscroll = (bp->lineno - (nlines - 1) / 2) - bp->topline;
  645.     if (nscroll > 0) {
  646.         XmTextScroll(text, nscroll);
  647.         bp->topline += nscroll;
  648.     }
  649.     }
  650.  
  651.     XmTextSetInsertionPosition(text, pos + bp->wordlen);
  652.  
  653.     sprintf(tmp, "%.*s", bp->wordlen, bp->ptr);
  654.     XmTextFieldSetString(textedit, tmp);
  655.  
  656.     sprintf(tmp, "+%u @%u", pos - bp->offset, pos);
  657.     xstr = XmStringCreateSimple(tmp);
  658.     XtVaSetValues(offsetNumber, XmNlabelString, xstr, NULL);
  659.  
  660.     ListPossibilities ();
  661.  
  662.     /*
  663.      * We don't use the XmTextSetSelection() because of a display bug...
  664.      */
  665.     HighlightText(text, pos, pos + bp->wordlen);
  666.  
  667. #ifdef    DOMOTION
  668.     ignoreMotion = 0;
  669. #endif
  670.  
  671. #ifdef    DOMOTION
  672.     ignoreMotion = 1;
  673. #endif
  674. }
  675.  
  676. #ifndef    DEBUG
  677. _dprintf() { }
  678. #endif
  679.  
  680. static void
  681. ListSelectCB(list, bp, lcb)
  682. Widget  list;
  683. buf_t    *bp;
  684. XmListCallbackStruct *lcb;
  685. {
  686.     char    *word;
  687.     long    pos = bp->offset + (bp->ptr - bp->base) + bp->delta;
  688.  
  689.     XmStringGetLtoR(lcb->item, XmSTRING_DEFAULT_CHARSET, &word);
  690.  
  691.     UnhighlightText(text, pos, pos + bp->wordlen);
  692.     XmTextReplace(text, pos, pos + bp->wordlen, word);
  693.     bp->changed = 1;
  694.  
  695.     bp->ptr += strlen(word);
  696.     bp->delta += (strlen(word) - bp->wordlen);
  697.     UnBlock();
  698. }
  699.  
  700. static void
  701. ReplaceCB(button, textedit, call_data)
  702. Widget    button;
  703. Widget    textedit;
  704. caddr_t    call_data;
  705. {
  706.     char    *word;
  707.     buf_t    *bp = &buf;        /* cheat! */
  708.     long    pos = bp->offset + (bp->ptr - bp->base) + bp->delta;
  709.  
  710.     word = XmTextFieldGetString(textedit);
  711.  
  712.     UnhighlightText(text, pos, pos + bp->wordlen);
  713.     XmTextReplace(text, pos, pos + bp->wordlen, word);
  714.     bp->changed = 1;
  715.  
  716.     bp->ptr += strlen(word);
  717.     bp->delta += (strlen(word) - bp->wordlen);
  718.     UnBlock();
  719. }
  720.  
  721. static void
  722. AcceptCB(button, bp, call_data)
  723. Widget    button;
  724. buf_t    *bp;
  725. caddr_t call_data;
  726. {
  727.     long    pos = bp->offset + (bp->ptr - bp->base) + bp->delta;
  728.  
  729.     UnhighlightText(text, pos, pos + bp->wordlen);
  730.     WriteCmd(srvout, "@%.*s\n", bp->wordlen, bp->ptr);
  731.  
  732.     bp->ptr += bp->wordlen;
  733.     UnBlock();
  734. }
  735.  
  736. static void
  737. InsertCB(button, bp, call_data)
  738. Widget    button;
  739. buf_t    *bp;
  740. caddr_t    call_data;
  741. {
  742.     long    pos = bp->offset + (bp->ptr - bp->base) + bp->delta;
  743.  
  744.     UnhighlightText(text, pos, pos + bp->wordlen);
  745.     WriteCmd(srvout, "*%.*s\n", bp->wordlen, bp->ptr);
  746.  
  747.     bp->ptr += bp->wordlen;
  748.     UnBlock();
  749. }
  750.  
  751. static void
  752. SkipCB(button, bp, call_data)
  753. Widget    button;
  754. buf_t    *bp;
  755. caddr_t call_data;
  756. {
  757.     long    pos = bp->offset + (bp->ptr - bp->base) + bp->delta;
  758.  
  759.     UnhighlightText(text, pos, pos + bp->wordlen);
  760.  
  761.     bp->ptr += bp->wordlen;
  762.     UnBlock();
  763. }
  764.  
  765. static void
  766. UncapCB(button, bp, call_data)
  767. Widget    button;
  768. buf_t    *bp;
  769. caddr_t call_data;
  770. {
  771.     long    pos = bp->offset + (bp->ptr - bp->base) + bp->delta;
  772.  
  773.     UnhighlightText(text, pos, pos + bp->wordlen);
  774.     WriteCmd(srvout, "%c%.*s\n", CUNCAP, bp->wordlen, bp->ptr);
  775.  
  776.     bp->ptr += bp->wordlen;
  777.     UnBlock();
  778. }
  779.  
  780. static void
  781. QuitCB(button, client_data, call_data)
  782. Widget    button;
  783. caddr_t    client_data;
  784. caddr_t    call_data;
  785. {
  786.     quit = 1;
  787.     UnBlock();
  788. }
  789.  
  790. static void
  791. AckCB(button, client_data, call_data)
  792. Widget    button;
  793. caddr_t    client_data;
  794. caddr_t    call_data;
  795. {
  796.     Widget    widget = XtParent(button);
  797.  
  798.     XtUnmanageChild(widget);
  799.     /* Unblocking... */
  800.     /* UnBlock(); */
  801. }
  802.  
  803. static void
  804. CancelAbortCB(button, client_data, call_data)
  805. Widget    button;
  806. caddr_t    client_data;
  807. caddr_t    call_data;
  808. {
  809.     Widget    isModifiedDialog = XtParent(button);
  810.  
  811.     XtUnmanageChild(isModifiedDialog);
  812. #if 0
  813.     UnBlock();
  814. #endif
  815. }
  816.  
  817. static void
  818. AbortOKCB(button, client_data, call_data)
  819. Widget    button;
  820. caddr_t    client_data;
  821. caddr_t    call_data;
  822. {
  823.     Widget    isModifiedDialog = XtParent(button);
  824.     buf_t    *bp = &buf;
  825.  
  826.     XtUnmanageChild(isModifiedDialog);
  827.  
  828.     bp->changed = 0;        /* we don't want to write the file */
  829.     quit = 1;
  830.     UnBlock();
  831. }
  832.  
  833. static void
  834. AbortCB(button, client_data, call_data)
  835. Widget    button;
  836. caddr_t    client_data;
  837. caddr_t call_data;
  838. {
  839.     buf_t    *bp = &buf;
  840.     int        exists = (isModifiedDialog != NULL);
  841.  
  842.     if (! bp->changed) {
  843.     quit = 1;
  844.     UnBlock();
  845.     return;
  846.     }
  847.  
  848.     PostWarning(&isModifiedDialog, "isModifiedDialog", NULL, False);
  849.     if (exists) return;
  850.  
  851.     XtManageChild(XmMessageBoxGetChild(isModifiedDialog, XmDIALOG_CANCEL_BUTTON));
  852.  
  853.     XtRemoveCallback(XmMessageBoxGetChild(isModifiedDialog, XmDIALOG_OK_BUTTON),
  854.         XmNactivateCallback, AckCB, NULL);
  855.     XtAddCallback(XmMessageBoxGetChild(isModifiedDialog, XmDIALOG_OK_BUTTON),
  856.          XmNactivateCallback, AbortOKCB, NULL);
  857.     XtAddCallback(XmMessageBoxGetChild(isModifiedDialog, XmDIALOG_CANCEL_BUTTON),
  858.          XmNactivateCallback, CancelAbortCB, NULL);
  859. }
  860.  
  861. static void
  862. PostWarning(widget, name, arg, block)
  863. Widget    *widget;
  864. char    *name;
  865. char    *arg;
  866. int    block;
  867. {
  868.     Widget    shell;
  869.     char    *newline;
  870.     XmString    tmp;
  871.     XmString    xstr;
  872.     void    _XmDestroyParentCallback();
  873.     char    buf[80];
  874.  
  875.     dprintf("PostWarning(0x%x, \"%s\", %s)\n", widget, name, arg);
  876.  
  877.     if (! *widget) {
  878.         shell = XtVaCreatePopupShell("Dialog_popup", xmDialogShellWidgetClass, toplevel,
  879.         XmNallowShellResize,    True,
  880.         XmNmwmDecorations,    MWM_DECOR_BORDER,
  881.         XmNtransient,        True,
  882.         NULL);
  883.  
  884.         *widget = XtVaCreateWidget(name, xmMessageBoxWidgetClass, shell,
  885.         XmNnoResize,        True,
  886.         XmNdialogStyle,        XmDIALOG_FULL_APPLICATION_MODAL,
  887.         XmNmessageAlignment,    XmALIGNMENT_CENTER,
  888.         NULL);
  889.  
  890.         XtAddCallback(*widget, XmNdestroyCallback, _XmDestroyParentCallback,
  891.         NULL);
  892.         XtUnmanageChild(XmMessageBoxGetChild(*widget, XmDIALOG_HELP_BUTTON));
  893.         XtUnmanageChild(XmMessageBoxGetChild(*widget, XmDIALOG_CANCEL_BUTTON));
  894.     XtAddCallback(XmMessageBoxGetChild(*widget, XmDIALOG_OK_BUTTON),
  895.         XmNactivateCallback, AckCB, NULL);
  896.  
  897.     /*
  898.      * We use the 'userData' value for storing away the string,
  899.      * since it gets clobbered by a sprintf()...
  900.      */
  901.         XtVaGetValues(*widget, XmNmessageString, &tmp, NULL);
  902.     XtVaSetValues(*widget, XmNuserData, tmp, NULL);
  903.     }
  904.  
  905.     XtVaGetValues(*widget, XmNuserData, &xstr, NULL);
  906.     XmStringGetLtoR(xstr, XmSTRING_DEFAULT_CHARSET, &tmp);
  907.     /*
  908.      * This is a bit of a kludge -- we replace any occurences of
  909.      * backslash with newlines.  I can't figure out how to protect
  910.      * these characters from Motif...  I suppose if using compound
  911.      * strings were slightly more obvious, I would use those.
  912.      */
  913.     while (newline = strchr(tmp, '\\'))
  914.     *newline = '\n';
  915.     sprintf(buf, tmp, arg);
  916. #if 0
  917.     XtFree(tmp);
  918.     dprintf("did free\n");
  919. #endif
  920.     xstr = XmStringCreateLtoR(buf, XmSTRING_DEFAULT_CHARSET);
  921.     XtVaSetValues(*widget,
  922.         XmNnoResize,        False,
  923.         XmNmessageString,    xstr,
  924.         NULL);
  925.     XtManageChild(*widget);
  926. }
  927.  
  928. #ifdef    DOMOTION
  929. static void
  930. MotionCB(text, client_data, mcb)
  931. Widget    text;
  932. caddr_t    client_data;
  933. XmTextVerifyCallbackStruct *mcb;
  934. {
  935.     long    pos = bp->offset + (bp->ptr - bp->base) + bp->delta;
  936.     long    newpos = mcb->newInsert;
  937.     int        n;
  938.  
  939.     if (ignoreMotion) return;
  940.  
  941.     ignoreMotion = 1;
  942.     dprintf("MotionCB(%d)\n", newpos);
  943.  
  944.     /*
  945.      * LINELEN is an arbitrary number here...
  946.      */
  947.     getbuf(bp, newpos - LINELEN);
  948.     bp->ptr += LINELEN;
  949.  
  950.     bp->ptr -= (n = skipbackword(bp->ptr, bp->base));
  951.     dprintf("new word is: %.20s\n", bp->ptr);
  952.  
  953.     /* we should eat up to an empty line before continuing! */
  954.     UnBlock();
  955. }
  956. #endif
  957.  
  958. void
  959. WriteCmd(fp, fmt, va_alist)
  960. FILE *fp;
  961. char *fmt;
  962. va_dcl
  963. {
  964.     va_list args;
  965.  
  966.     va_start(args);
  967.  
  968. #ifdef    DEBUG
  969.     printf(">>>");
  970.     (void)vprintf(fmt, args);
  971. #endif
  972.  
  973.     (void)vfprintf(fp, fmt, args);
  974.     fflush(fp);
  975.     va_end(args);
  976. }
  977.  
  978. #if 0
  979. static String fallback_resources[] = {
  980. "*isReadonlyDialog*messageString:    Notice:  File is read-only.",
  981. "*tempIsDialog*messageString:        \
  982. Warning:  File is read-only; modified\\\\\
  983. file is '%s'.",
  984. "*couldntSaveDialog*messageString:    Error:  Couldn't save modified file.",
  985. "*noBackupDialog*messageString:        Warning:  Couldn't write backup file.",
  986. "*isModifiedDialog*messageString:    Warning:  File has been modified;\\\\\
  987. Do you really want to quit?",
  988. "*fileLabel.labelString:        File:",
  989. "*lineLabel.labelString:        Line:",
  990. "*offsetLabel.labelString:        Offset:",
  991. "*wordLabel.labelString:        Word:",
  992. "*psblLabel.labelString:        Possibilities:",
  993. "*actions.skipButton.labelString:    Skip",
  994. "*actions.replButton.labelString:    Replace",
  995. "*actions.acptButton.labelString:    Accept",
  996. "*actions.insrButton.labelString:    Insert",
  997. "*actions.lookButton.labelString:    Lookup",
  998. "*actions.uncpButton.labelString:    Uncap.",
  999. "*actions.quitButton.labelString:    Quit",
  1000. "*actions.abrtButton.labelString:    Abort",
  1001. "*actions.helpButton.labelString:    Help",
  1002. "*isReadonlyDialog*dialogType:        DIALOG_INFORMATION",
  1003. "*couldntSaveDialog*dialogType:        DIALOG_ERROR",
  1004. "*tempIsDialog*dialogType:        DIALOG_WARNING",
  1005. "*noBackupDialog*dialogType:        DIALOG_WARNING",
  1006. "*isModifiedDialog*dialogType:        DIALOG_WARNING",
  1007. "*fileView.rows:            10",
  1008. "*fileView.columns:            80",
  1009. "*fileView.scrollVertical:        True",
  1010. "*fileView.scrollHorizontal:         False",
  1011. "*separator.separatorType:        SINGLE_LINE",
  1012. NULL};
  1013. #endif
  1014.  
  1015. static XrmOptionDescRec options[] = {
  1016.     {"-c",        "*columns",    XrmoptionStickyArg,    NULL},
  1017.     {"-d",        "*dictionary",    XrmoptionStickyArg,    NULL},
  1018.     {"-T",        "*type",    XrmoptionStickyArg,    NULL},
  1019.     {"-t",        "*type",    XrmoptionNoArg,        "tex"},
  1020.     {"-n",        "*type",    XrmoptionNoArg,        "nroff"},
  1021.     {"-b",        "*backup",    XrmoptionNoArg,        "True"},
  1022.     {"-x",        "*backup",    XrmoptionNoArg,        "False"},
  1023.     {"-C",        "*haveCompounds", XrmoptionNoArg,    "True"},
  1024.     {"-S",        "*sortPossibilities", XrmoptionNoArg,    "True"},
  1025. };
  1026.  
  1027.  
  1028. #define    XtNcolumns    "columns"
  1029. #define    XtCColumns    "Columns"
  1030. #define    XtNdictionary    "dictionary"
  1031. #define    XtCDictionary    "Dictionary"
  1032. #define    XtNtype        "type"
  1033. #define    XtCType        "Type"
  1034. #define    XtNbackup    "backup"
  1035. #define    XtCBackup    "Backup"
  1036. #define    XtNhaveCompounds "haveCompounds"
  1037. #define    XtCHaveCompounds "HaveCompounds"
  1038. #define    XtNsortPossibilities "sortPossibilities"
  1039. #define    XtCSortPossibilities "SortPossibilities"
  1040.  
  1041. static XtResource resources[] = {
  1042.     {
  1043.     XtNcolumns,        XtCColumns,
  1044.     XtRInt,            sizeof(int),
  1045.     XtOffsetOf(AppData,columns),
  1046.     XtRImmediate,        (XtPointer) NCOLS,
  1047.     },
  1048.     {
  1049.     XtNdictionary,        XtCDictionary,
  1050.     XtRString,        sizeof(String),
  1051.     XtOffsetOf(AppData,dictionary),
  1052.     XtRImmediate,        (XtPointer) "english",
  1053.     },
  1054.     {
  1055.     XtNtype,        XtCType,
  1056.     XtRString,        sizeof(String),
  1057.     XtOffsetOf(AppData,type),
  1058.     XtRImmediate,        (XtPointer) "nroff",
  1059.     },
  1060.     {
  1061.     XtNbackup,        XtCBackup,
  1062.     XtRBoolean,        sizeof(Boolean),
  1063.     XtOffsetOf(AppData,backup),
  1064.     XtRImmediate,        (XtPointer) True,
  1065.     },
  1066.     {
  1067.     XtNhaveCompounds,    XtCHaveCompounds,
  1068.     XtRBoolean,        sizeof(Boolean),
  1069.     XtOffsetOf(AppData,haveCompounds),
  1070.     XtRImmediate,        (XtPointer) False,
  1071.     },
  1072.     {
  1073.     XtNsortPossibilities,    XtCSortPossibilities,
  1074.     XtRBoolean,        sizeof(Boolean),
  1075.     XtOffsetOf(AppData,sortPossibilities),
  1076.     XtRImmediate,        (XtPointer) False,
  1077.     },
  1078. };
  1079.  
  1080. static XtAppContext app_context;
  1081. static Widget    toplevel;
  1082. static Widget    actions;
  1083. static Widget    fileName;
  1084. static Widget    lineNumber;
  1085. static Widget    offsetNumber;
  1086. static Widget    text;
  1087. static Widget    textedit;
  1088. static Widget    list[NCOLS];
  1089. static Widget    noBackupDialog;
  1090. static Widget    isReadonlyDialog;
  1091. static Widget    couldntSaveDialog;
  1092. static Widget    tempIsDialog;
  1093. static Widget    isModifiedDialog;
  1094.  
  1095. void
  1096. CreateWidgets(toplevel)
  1097. Widget    toplevel;
  1098. {
  1099.     Widget    shell;
  1100.     Widget    mainwin;
  1101.     Widget    psblRC;
  1102.     Widget    button;
  1103.     Widget    subform, subform2;
  1104.     Widget    frame;
  1105.     Widget    fileLabel, lineLabel, offsetLabel;
  1106.     Widget    psblLabel, wordLabel;
  1107.     Widget    form;
  1108.     Widget    scrolledWindow;
  1109.     void    _XmDestroyParentCallback();
  1110.     int        i;
  1111.  
  1112.     if (app_data.columns > NCOLS) app_data.columns = NCOLS;
  1113.  
  1114.     mainwin = XmCreateMainWindow (toplevel, "main", NULL, 0);
  1115.     XtManageChild (mainwin);
  1116.  
  1117. #if 0
  1118.     /*
  1119.      * Create all our pop-up shells and message boxes here...
  1120.      */
  1121.     shell = XtVaCreatePopupShell("abortDialog_popup", xmDialogShellWidgetClass, toplevel,
  1122.         XmNallowShellResize,    True,
  1123.         XmNmwmDecorations,    MWM_DECOR_BORDER,
  1124.         XmNtransient,        True,
  1125.         NULL);
  1126.  
  1127.     abortMsg = XtVaCreateWidget("abortDialog", xmMessageBoxWidgetClass, shell,
  1128.         XmNnoResize,        True,
  1129.         XmNdialogStyle,        XmDIALOG_FULL_APPLICATION_MODAL,
  1130.         XmNmessageAlignment,    XmALIGNMENT_CENTER,
  1131.         NULL);
  1132.  
  1133.     XtAddCallback(abortMsg, XmNdestroyCallback, _XmDestroyParentCallback, NULL);
  1134.     XtUnmanageChild(XmMessageBoxGetChild(abortMsg, XmDIALOG_HELP_BUTTON));
  1135.  
  1136.     XtAddCallback(XmMessageBoxGetChild(abortMsg, XmDIALOG_OK_BUTTON),
  1137.          XmNactivateCallback, AbortOKCB, NULL);
  1138.     XtAddCallback(XmMessageBoxGetChild(abortMsg, XmDIALOG_CANCEL_BUTTON),
  1139.          XmNactivateCallback, CancelAbortCB, NULL);
  1140. #endif
  1141.  
  1142.     form = XtCreateManagedWidget("form", xmFormWidgetClass, mainwin, NULL, 0);
  1143.  
  1144.     /*
  1145.      * Do subform containing file name, line, and character offset...
  1146.      */
  1147.     subform = XtVaCreateManagedWidget("subform1", xmFormWidgetClass, form,
  1148.         XmNtopAttachment,    XmATTACH_FORM,
  1149.         XmNleftAttachment,    XmATTACH_FORM,
  1150.         XmNrightAttachment,    XmATTACH_FORM,
  1151.         NULL);
  1152.  
  1153.     fileLabel = XtVaCreateManagedWidget("fileLabel", xmLabelWidgetClass, subform,
  1154.         XmNtopAttachment,    XmATTACH_FORM,
  1155.         XmNbottomAttachment,    XmATTACH_FORM,
  1156.         XmNleftAttachment,    XmATTACH_FORM,
  1157. #if 0
  1158.         XmNleftOffset,        2,
  1159. #endif
  1160.         NULL);
  1161.  
  1162.     fileName = XtVaCreateManagedWidget("fileName", xmLabelWidgetClass, subform,
  1163.         XmNtopAttachment,    XmATTACH_FORM,
  1164.         XmNbottomAttachment,    XmATTACH_FORM,
  1165.         XmNleftAttachment,    XmATTACH_WIDGET,
  1166.         XmNleftWidget,        fileLabel,
  1167.         XmNshadowThickness,    2,
  1168.         NULL);
  1169.  
  1170.     lineLabel = XtVaCreateManagedWidget("lineLabel", xmLabelWidgetClass, subform,
  1171.         XmNtopAttachment,    XmATTACH_FORM,
  1172.         XmNbottomAttachment,    XmATTACH_FORM,
  1173.         XmNleftAttachment,    XmATTACH_WIDGET,
  1174.         XmNleftWidget,        fileName,
  1175.         NULL);
  1176.  
  1177.     lineNumber = XtVaCreateManagedWidget("lineNumber", xmLabelWidgetClass, subform,
  1178.         XmNtopAttachment,    XmATTACH_FORM,
  1179.         XmNbottomAttachment,    XmATTACH_FORM,
  1180.         XmNleftAttachment,    XmATTACH_WIDGET,
  1181.         XmNleftWidget,        lineLabel,
  1182.         XmNshadowThickness,    2,
  1183.         NULL);
  1184.  
  1185.     offsetLabel = XtVaCreateManagedWidget("offsetLabel", xmLabelWidgetClass, subform,
  1186.         XmNtopAttachment,    XmATTACH_FORM,
  1187.         XmNbottomAttachment,    XmATTACH_FORM,
  1188.         XmNleftAttachment,    XmATTACH_WIDGET,
  1189.         XmNleftWidget,        lineNumber,
  1190.         NULL);
  1191.  
  1192.     offsetNumber = XtVaCreateManagedWidget("offsetNumber", xmLabelWidgetClass, subform,
  1193.         XmNtopAttachment,    XmATTACH_FORM,
  1194.         XmNbottomAttachment,    XmATTACH_FORM,
  1195.         XmNleftAttachment,    XmATTACH_WIDGET,
  1196.         XmNleftWidget,        offsetLabel,
  1197.         XmNshadowThickness,    2,
  1198.         NULL);
  1199.  
  1200.     /*
  1201.      * file viewport done as multi-line text widget...
  1202.      */
  1203.     scrolledWindow = XtVaCreateManagedWidget("fileViewSW", xmScrolledWindowWidgetClass, form,
  1204.         XmNtopAttachment,    XmATTACH_WIDGET,
  1205.         XmNtopWidget,        subform,
  1206.         XmNtopOffset,        2,
  1207.         XmNleftAttachment,    XmATTACH_FORM,
  1208.         XmNleftOffset,        2,
  1209.         XmNrightAttachment,    XmATTACH_FORM,
  1210.         XmNrightOffset,        2,
  1211.         XmNscrollingPolicy,    XmAPPLICATION_DEFINED,
  1212.         XmNvisualPolicy,    XmVARIABLE,
  1213.         XmNscrollBarDisplayPolicy, XmSTATIC,
  1214.         XmNshadowThickness,    0,
  1215.         NULL);
  1216.  
  1217.     text = XtVaCreateManagedWidget("fileView", xmTextWidgetClass, scrolledWindow,
  1218.         XmNeditMode,        XmMULTI_LINE_EDIT,
  1219.         XmNeditable,        False,
  1220.         XmNautoShowCursorPosition, False,
  1221.         NULL);
  1222.     XtAddCallback(text, XmNdestroyCallback, _XmDestroyParentCallback, NULL);
  1223. #ifdef    DOMOTION
  1224.     XtAddCallback(text, XmNmotionVerifyCallback, MotionCB, NULL);
  1225. #endif
  1226.  
  1227.     /*
  1228.      * word editing box...
  1229.      */
  1230.     subform = XtVaCreateManagedWidget("subform", xmFormWidgetClass, form,
  1231.         XmNtopAttachment,    XmATTACH_WIDGET,
  1232.         XmNtopWidget,        text,
  1233.         XmNtopOffset,        2,
  1234.         XmNleftAttachment,    XmATTACH_FORM,
  1235.         XmNrightAttachment,    XmATTACH_FORM,
  1236.         NULL);
  1237.  
  1238.     wordLabel = XtVaCreateManagedWidget("wordLabel", xmLabelWidgetClass, subform,
  1239.         XmNtopAttachment,    XmATTACH_FORM,
  1240.         XmNbottomAttachment,    XmATTACH_FORM,
  1241.         XmNleftAttachment,    XmATTACH_FORM,
  1242.         XmNleftOffset,        2,
  1243.         NULL);
  1244.  
  1245.     textedit = XtVaCreateManagedWidget("wordBuffer", xmTextFieldWidgetClass, subform,
  1246.         XmNtopAttachment,    XmATTACH_FORM,
  1247.         XmNbottomAttachment,    XmATTACH_FORM,
  1248.         XmNleftAttachment,    XmATTACH_WIDGET,
  1249.         XmNleftWidget,        wordLabel,
  1250.         XmNrightAttachment,    XmATTACH_FORM,
  1251.         NULL);
  1252.     XtAddCallback(textedit, XmNactivateCallback, ReplaceCB, textedit);
  1253.  
  1254.     subform2 = XtVaCreateManagedWidget("subform", xmFormWidgetClass, form,
  1255.         XmNtopAttachment,    XmATTACH_WIDGET,
  1256.         XmNtopWidget,        subform,
  1257.         XmNtopOffset,        2,
  1258.         XmNleftAttachment,    XmATTACH_FORM,
  1259.         XmNrightAttachment,    XmATTACH_FORM,
  1260.         XmNbottomAttachment,    XmATTACH_FORM,
  1261.         NULL);
  1262.  
  1263.     frame = XtVaCreateManagedWidget("buttonBoxFrame", xmFrameWidgetClass, subform2,
  1264.         XmNtopAttachment,    XmATTACH_FORM,
  1265.         XmNbottomAttachment,    XmATTACH_FORM,
  1266.         XmNbottomOffset,    2,
  1267.         XmNrightAttachment,    XmATTACH_FORM,
  1268.         XmNrightOffset,        2,
  1269.         NULL);
  1270.  
  1271.     /*
  1272.      * Create list of action buttons as row/column widget...
  1273.      */
  1274.     actions = XtVaCreateManagedWidget("actions", xmRowColumnWidgetClass, frame,
  1275.         XmNorientation,        XmVERTICAL,
  1276.         XmNpacking,        XmPACK_COLUMN,
  1277.         XmNnumColumns,        2,
  1278.         XmNadjustLast,        False,
  1279.         NULL);
  1280.  
  1281.     /* can we put this into a structure? */
  1282.     button = XmCreatePushButtonGadget(actions, "skipButton", NULL, 0);
  1283.     XtManageChild(button);
  1284.     XtAddCallback(button, XmNactivateCallback, SkipCB, &buf);
  1285.  
  1286.     button = XmCreatePushButtonGadget(actions, "replButton", NULL, 0);
  1287.     XtManageChild(button);
  1288.     XtAddCallback(button, XmNactivateCallback, ReplaceCB, textedit);
  1289.  
  1290.     button = XmCreatePushButtonGadget(actions, "acptButton", NULL, 0);
  1291.     XtManageChild(button);
  1292.     XtAddCallback(button, XmNactivateCallback, AcceptCB, &buf);
  1293.  
  1294.     button = XmCreatePushButtonGadget(actions, "insrButton", NULL, 0);
  1295.     XtManageChild(button);
  1296.     XtAddCallback(button, XmNactivateCallback, InsertCB, &buf);
  1297.  
  1298.     button = XmCreatePushButtonGadget(actions, "lookButton", NULL, 0);
  1299.     XtManageChild(button);
  1300.  
  1301.     button = XmCreatePushButtonGadget(actions, "uncpButton", NULL, 0);
  1302.     XtManageChild(button);
  1303.     XtAddCallback(button, XmNactivateCallback, UncapCB, &buf);
  1304.  
  1305.     button = XmCreatePushButtonGadget(actions, "quitButton", NULL, 0);
  1306.     XtManageChild(button);
  1307.     XtAddCallback(button, XmNactivateCallback, QuitCB, NULL);
  1308.  
  1309.     button = XmCreatePushButtonGadget(actions, "abrtButton", NULL, 0);
  1310.     XtManageChild(button);
  1311.     XtAddCallback(button, XmNactivateCallback, AbortCB, NULL);
  1312.  
  1313.     button = XmCreatePushButtonGadget(actions, "helpButton", NULL, 0);
  1314.     XtManageChild(button);
  1315.  
  1316.  
  1317.     psblLabel = XtVaCreateManagedWidget("psblLabel", xmLabelWidgetClass, subform2,
  1318.         XmNtopAttachment,    XmATTACH_FORM,
  1319.         XmNleftAttachment,    XmATTACH_FORM,
  1320.         XmNrightAttachment,    XmATTACH_WIDGET,
  1321.         XmNrightWidget,        frame,
  1322.         NULL);
  1323.  
  1324.     /*
  1325.      * Create R/C widget with word possibilities in list widgets
  1326.      */
  1327.     psblRC = XtVaCreateManagedWidget("psblRC", xmRowColumnWidgetClass, subform2,
  1328.         XmNtopAttachment,    XmATTACH_WIDGET,
  1329.         XmNtopWidget,        psblLabel,
  1330.         XmNleftAttachment,    XmATTACH_FORM,
  1331.         XmNleftOffset,        2,
  1332.         XmNrightAttachment,    XmATTACH_WIDGET,
  1333.         XmNrightWidget,        frame,
  1334.         XmNbottomAttachment,    XmATTACH_FORM,
  1335. #if 1
  1336.         XmNpacking,        XmPACK_COLUMN,
  1337.         XmNnumColumns,        app_data.columns,
  1338.         XmNorientation,        XmVERTICAL,
  1339. #else
  1340.         XmNpacking,        XmPACK_TIGHT,
  1341.         XmNnumColumns,        1,
  1342.         XmNorientation,        XmHORIZONTAL,
  1343. #endif
  1344.         XmNadjustLast,        False,
  1345.         NULL);
  1346.  
  1347.     for (i = 0; i < app_data.columns; ++i) {
  1348.     list[i] = XtVaCreateManagedWidget("psbList", xmListWidgetClass, psblRC,
  1349.         XmNselectionPolicy,    XmSINGLE_SELECT,
  1350. #if 1
  1351.         XmNscrollBarDisplayPolicy, XmAS_NEEDED,
  1352.         XmNvisibleItemCount,    NENTRIES,
  1353.         XmNlistSizePolicy,    XmVARIABLE,
  1354. #endif
  1355.         NULL);
  1356.     XtAddCallback(list[i], XmNsingleSelectionCallback, ListSelectCB, &buf);
  1357.     }
  1358.  
  1359.     /* what, nothing else? */
  1360. }
  1361.  
  1362.  
  1363. main(argc, argv)
  1364. char *argv[];
  1365. {
  1366.     char    *myname, *slash;
  1367.     int        i;
  1368.     char    **files;
  1369.  
  1370.     myname = argv[0];
  1371.     if (slash = strrchr(myname, '/'))
  1372.     myname = ++slash;
  1373.  
  1374.     toplevel = XtAppInitialize (&app_context, "Xspell",
  1375. #if 0
  1376.         options, XtNumber(options), &argc, argv, fallback_resources,
  1377. #else
  1378.         options, XtNumber(options), &argc, argv, NULL,
  1379. #endif
  1380.         NULL, 0);
  1381.  
  1382.     XtVaGetApplicationResources(toplevel, &app_data,
  1383.     resources, XtNumber(resources), NULL);
  1384.  
  1385.     if (argc == 1) {
  1386.     fprintf(stderr, "usage: %s file1 [ file2 ] ...\n", myname);
  1387.     exit(1);
  1388.     }
  1389.  
  1390.     CreateWidgets (toplevel);
  1391.     XtRealizeWidget (toplevel);
  1392.  
  1393.     Connect(toplevel);
  1394.  
  1395.     files = calloc(argc, sizeof(char *));
  1396.  
  1397.     for (i = 1; i < argc; ++i)
  1398.     files[i - 1] = argv[i];
  1399.     files[argc - 1] = NULL;
  1400.  
  1401.     filePtr = &files[0];
  1402.  
  1403.     StartFile();
  1404.     Loop();
  1405. }
  1406.